#include "luabind_export.h"

namespace SkyID
{

//- LuabindExport ------------------------------------------------------------

namespace LuabindExport
{

LuabindExportStruct *luabindExport = NULL;

// for LogFlags
struct image_constants {};
// for GLenum
struct gl_constants {};
// for KeyCode
struct keycode_constants {};
// for KeyMod
struct keymod_constants {};
// for MouseButton
struct mousebutton_constants {};

bool initialize(lua_State *VM)
{
	luabindExport = new LuabindExportStruct(VM);
	return true;
}

void shutdown()
{
	delete luabindExport;
	luabindExport = NULL;
}

LuabindExportStruct::LuabindExportStruct(lua_State *VM)
{
	using namespace luabind;

	open(VM);

	module(VM)
	[
		// geom.h
		class_<Point>("Point")
			.def_readwrite("x", &Point::x)
			.def_readwrite("y", &Point::y),
		class_<Rect>("Rect")
			.def_readwrite("p1", &Rect::p1)
			.def_readwrite("p2", &Rect::p2)
			.def_readwrite("x", &Rect::x)
			.def_readwrite("y", &Rect::y)
			.def_readwrite("w", &Rect::w)
			.def_readwrite("h", &Rect::h),
		class_<Vertex>("Vertex")
			.def_readwrite("pos", &Vertex::pos)
			.def_readwrite("tex", &Vertex::tex)
			.def_readwrite("x", &Vertex::x)
			.def_readwrite("y", &Vertex::y)
			.def_readwrite("u", &Vertex::u)
			.def_readwrite("v", &Vertex::v),
		class_<Color>("Color")
			.def_readwrite("r", &Color::r)
			.def_readwrite("g", &Color::g)
			.def_readwrite("b", &Color::b)
			.def_readwrite("a", &Color::a),

		// object.h
		class_<Object>("Object")
			.def("isValid", &Object::isValid),

		// reader.h
		class_<Reader,Object>("Reader")
			.def("read", &Reader::read)
			.def("tell", &Reader::tell)
			.def("reset", &Reader::reset)
			.def("size", &Reader::size),
		class_<ReaderFile,Reader>("ReaderFile")
			.def(constructor<const char*>()),
		class_<ReaderZip,Reader>("ReaderZip")
			.def(constructor<const char*,const char*>()),

		// image.h
		class_<image_constants>("ImageFormat")
			.enum_("constants")
			[
				value("FORMAT_UNKNOWN", FORMAT_UNKNOWN),
				value("FORMAT_RGB", FORMAT_RGB),
				value("FORMAT_RGBA", FORMAT_RGBA)
			],
		class_<Image,Object>("Image")
			.def(constructor<const Image&>())
			.def("getWidth", &Image::getWidth)
			.def("getHeight", &Image::getHeight)
			.def("getFormat", &Image::getFormat)
			.def("getData", &Image::getData),
		class_<ImageJPEG,Image>("ImageJPEG")
			.def(constructor<Reader*>())
			.def("open", &ImageJPEG::open),
		class_<ImagePNG,Image>("ImagePNG")
			.def(constructor<Reader*>())
			.def("open", &ImagePNG::open),

#ifndef SKYID_DISABLE_SOUND
		// sound.h
		class_<Sound,Object>("Sound")
			.def("play", &Sound::play)
			.def("stop", &Sound::stop)
			.def("pause", &Sound::pause)
			.def("isPlaying", &Sound::isPlaying)
			.def("isPaused", &Sound::isPaused),
		class_<SoundWAV,Sound>("SoundWAV")
			.def(constructor<Reader*>()),
		class_<SoundOGG,Sound>("SoundOGG")
			.def(constructor<Reader*>()),

		// music.h
		class_<Music,Sound>("Music")
			.def("update", &Music::update),
		class_<MusicOGG,Music>("MusicOGG")
			.def(constructor<Reader*>()),
#endif

		// texture.h
		class_<gl_constants>("GL")
			.enum_("constants")
			[
				value("CLAMP", GL_CLAMP),
				value("REPEAT", GL_REPEAT)
			],
		class_<Texture,Object>("Texture")
			.def(constructor<const Image*,GLint>())
			.def("create", &Texture::create)
			.def("getID", &Texture::getID)
			.def("getWidth", &Texture::getWidth)
			.def("getHeight", &Texture::getHeight)
			.def("getFormat", &Texture::getFormat)
			.def("getTarget", &Texture::getTarget),

		// sprite.h
		class_<Sprite,Object>("Sprite")
			.def(constructor<const Texture*,float,float,float,float>())
			.def("flip", &Sprite::flip)
			.def("setTextureRect", &Sprite::setTextureRect)
			.def("getTexture", &Sprite::getTexture)
			.def("getWidth", &Sprite::getWidth)
			.def("getHeight", &Sprite::getHeight)
			.def("getTextureRect", &Sprite::getTextureRect),

		// vfs.h
		namespace_("VFS")
		[
			def("addPackage", &VFS::addPackage),
			def("removeAllPackages", &VFS::removeAllPackages)
		],

		// resource_manager.h
		namespace_("ResourceManager")
		[
			def("loadImage", &ResourceManager::loadImage),
			def("loadTexture", &ResourceManager::loadTexture),
			def("loadSound", &ResourceManager::loadSound),
			def("loadMusic", &ResourceManager::loadMusic)
		],

		// render.h
		namespace_("Render")
		[
			def("beginScene", &Render::beginScene),
			def("endScene", &Render::endScene),
			def("setTextureEnbale", &Render::setTextureEnbale),
			def("bindTexture", &Render::bindTexture),
			def("setColor", &Render::setColor),
			def("renderVertices", &Render::renderVertices),
			def("renderSprite", &Render::renderSprite)
		],

		// windows_event.h
		class_<keycode_constants>("KeyCode")
			.enum_("constants")
			[
				value("UNKNOWN", KEY_UNKNOWN),
				value("FIRST", KEY_FIRST),
				value("RETURN", KEY_RETURN),
				value("PAUSE", KEY_PAUSE),
				value("ESCAPE", KEY_ESCAPE),
				value("SPACE", KEY_SPACE),
				value("UP", KEY_UP),
				value("DOWN", KEY_DOWN),
				value("RIGHT", KEY_RIGHT),
				value("LEFT", KEY_LEFT),
				value("NUMLOCK", KEY_NUMLOCK),
				value("CAPSLOCK", KEY_CAPSLOCK),
				value("SCROLLOCK", KEY_SCROLLOCK),
				value("RSHIFT", KEY_RSHIFT),
				value("LSHIFT", KEY_LSHIFT),
				value("RCTRL", KEY_RCTRL),
				value("LCTRL", KEY_LCTRL),
				value("RALT", KEY_RALT),
				value("LALT", KEY_LALT),
				value("RMETA", KEY_RMETA),
				value("LMETA", KEY_LMETA),
				value("LSUPER", KEY_LSUPER),
				value("RSUPER", KEY_RSUPER),
				value("MODE", KEY_MODE),
				value("COMPOSE", KEY_COMPOSE)
			],
		class_<keymod_constants>("KeyMod")
			.enum_("constants")
			[
				value("NONE", MOD_NONE),
				value("LSHIFT", MOD_LSHIFT),
				value("RSHIFT", MOD_RSHIFT),
				value("LCTRL", MOD_LCTRL),
				value("RCTRL", MOD_RCTRL),
				value("LALT", MOD_LALT),
				value("RALT", MOD_RALT),
				value("SHIFT", MOD_LSHIFT|MOD_RSHIFT),
				value("CTRL", MOD_LCTRL|MOD_RCTRL),
				value("ALT", MOD_LALT|MOD_RALT)
			],
		class_<mousebutton_constants>("MouseButton")
			.enum_("constants")
			[
				value("LEFT", BUTTON_LEFT),
				value("MIDDLE", BUTTON_MIDDLE),
				value("RIGHT", BUTTON_RIGHT),
				value("WHEELUP", BUTTON_WHEELUP),
				value("WHEELDOWN", BUTTON_WHEELDOWN)
			],
		class_<MouseButtonEvent>("MouseButtonEvent")
			.def_readwrite("pressed", &MouseButtonEvent::pressed)
			.def_readwrite("x", &MouseButtonEvent::x)
			.def_readwrite("y", &MouseButtonEvent::y)
			.def_readwrite("button", &MouseButtonEvent::button),
		class_<MouseMotionEvent>("MouseMotionEvent")
			.def_readwrite("x", &MouseMotionEvent::x)
			.def_readwrite("y", &MouseMotionEvent::y)
			.def_readwrite("dx", &MouseMotionEvent::dx)
			.def_readwrite("dy", &MouseMotionEvent::dy),
		class_<KeyboardEvent>("KeyboardEvent")
			.def_readwrite("pressed", &KeyboardEvent::pressed)
			.def_readwrite("key", &KeyboardEvent::key)
			.def_readwrite("mod", &KeyboardEvent::mod),

		// window.h
		namespace_("Window")
		[
			def("processEvents", &Window::processEvents),
			def("swapBuffers", &Window::swapBuffers),
			def("getWidth", &Window::getWidth),
			def("getHeight", &Window::getHeight),
			def("getTicks", &Window::getTicks),
			def("getKeyState", &Window::getKeyState),
			def("quit", &Window::quit),
			def("setKeyboardCallback", &LuabindExportStruct::setKeyboardCallback),
			def("setMouseMotionCallback", &LuabindExportStruct::setMouseMotionCallback),
			def("setMouseButtonCallback", &LuabindExportStruct::setMouseButtonCallback)
		],

		// engine.h
		namespace_("Engine")
		[
			def("process", &Engine::process),
			def("quit", &Engine::quit),
			def("setRenderCallback", &LuabindExportStruct::setRenderCallback),
			def("setAnimateCallback", &LuabindExportStruct::setAnimateCallback)
		],

		// script_engine.h
		namespace_("ScriptEngine")
		[
			def("parseFile", &ScriptEngine::parseFile)
		]
	];
}

void LuabindExportStruct::keyboardCallback(const KeyboardEvent &event)
{
	luabindExport->mKeyboardCallback(event);
}

void LuabindExportStruct::mouseMotionCallback(const MouseMotionEvent &event)
{
	luabindExport->mMouseMotionCallback(event);
}

void LuabindExportStruct::mouseButtonCallback(const MouseButtonEvent &event)
{
	luabindExport->mMouseButtonCallback(event);
}

void LuabindExportStruct::setKeyboardCallback(luabind::object const &callback)
{
	Window::setKeyboardCallback(&keyboardCallback);
	luabindExport->mKeyboardCallback = callback;
}

void LuabindExportStruct::setMouseMotionCallback(luabind::object const &callback)
{
	Window::setMouseMotionCallback(&mouseMotionCallback);
	luabindExport->mMouseMotionCallback = callback;
}

void LuabindExportStruct::setMouseButtonCallback(luabind::object const &callback)
{
	Window::setMouseButtonCallback(&mouseButtonCallback);
	luabindExport->mMouseButtonCallback = callback;
}

void LuabindExportStruct::renderCallback()
{
	luabindExport->mRenderCallback();
}

void LuabindExportStruct::animateCallback(float dt)
{
	luabindExport->mAnimateCallback(dt);
}

void LuabindExportStruct::setRenderCallback(luabind::object const &callback)
{
	Engine::setRenderCallback(&renderCallback);
	luabindExport->mRenderCallback = callback;
}

void LuabindExportStruct::setAnimateCallback(luabind::object const &callback)
{
	Engine::setAnimateCallback(&animateCallback);
	luabindExport->mAnimateCallback = callback;
}

} // namespace LuabindExport

} // namespace SkyID
